Chart / Charts / Chart Types / Cartesian / Series / Surface Series / Mesh Surface Series
In This Topic
    Mesh Surface Series
    In This Topic

    The Mesh Surface chart displays a surface with user-defined elevation, x-position and z-position values for each data point. Data points are ordered in a rectangular grid. Mesh surface series are represented by the NMeshSurfaceSeries type. The following figure displays a Mesh Surface chart:

     

     

     Creating a Mesh Surface Series

    To create a mesh surface you have to create an instance of the NMeshSurfaceSeries type and add it to the series collection of the chart. Surface series can be displayed only in 3D mode, so it is required to enable 3D for the chart hosting the series. The following code shows how to create a new mesh surface series and add it to the chart:

    C#
    Copy Code
    // setup chart
    NCartesianChart chart = (NCartesianChart)chartView.Surface.Charts[0];
    chart.Enable3D = true;
    // set aspect 1:1:1
    chart.ModelWidth = 50;
    chart.ModelHeight = 50;
    chart.ModelDepth = 50;
    
    // set projection
    chart.Projection.SetPredefinedProjection(ENPredefinedProjection.PerspectiveTilted);
    // create a surface series
    NMeshSurfaceSeries surface = new NMeshSurfaceSeries();
    // add the series to the chart series collection
    chart.Series.Add(surface);
    

     

     Mesh Surface Data

    The mesh surface data is represented by a NMeshSurfaceData object, which is accessible through the Data property of the NMeshSurfaceSeries class. The data is stored in a two-dimensional array of data points, where each data point has an elevation value, x-position value, and z-position value.
    The size of the grid is controlled with the help of the SetGridSize method of the NMeshSurfaceData object. It accepts two integer parameters - sizeX (defines the number of data points in the X dimension) and sizeZ (defines the number of data points in the Z dimension).


    To set the individual X/Y/Z coordinates of a surface data point you can use the following methods:
    SetValueY - for elevation values,
    SetValueX - for X-position values,
    SetValueZ - for Z-position values.
    The SetValue method sets all three values at a specified X and Z index. The supplied values must be of type System.Double. If you need to specify an invalid data point at some position you have to use DBNull.Value instead of a double value. The following example creates a mesh surface series with 9 data points (4 segments) and fills some data in it.

     

    C#
    Copy Code
    // obtain a reference to the Cartesian chart that is created by default
    NCartesianChart chart = (NCartesianChart)chartView.Surface.Charts[0];
    chart.Enable3D = true;
    // set aspect 1:1:1
    chart.ModelWidth = 50;
    chart.ModelHeight = 50;
    chart.ModelDepth = 50;
    // set projection
    chart.Projection.SetPredefinedProjection(ENPredefinedProjection.PerspectiveTilted);
    // create a surface series
    NMeshSurfaceSeries surface = new NMeshSurfaceSeries();
    chart.Series.Add(surface);
    surface.FrameMode = ENSurfaceFrameMode.Mesh;
    surface.Name = "Mesh Surface";
    
    // add some data
    surface.Data.SetGridSize(3, 3);
    surface.Data.SetValue(0, 0, 0.8, 0.0, 1.1);
    surface.Data.SetValue(1, 0, 0.0, 12.7, 0.0);
    surface.Data.SetValue(2, 0, 0.0, 17.0, 1.2);
    surface.Data.SetValue(0, 1, 1.0, 5.0, 12.0);
    surface.Data.SetValue(1, 1, 1.2, 10.0, 11.0);
    surface.Data.SetValue(2, 1, 0.5, 18.0, 10.0);
    surface.Data.SetValue(0, 2, 4.0, 2.1, 22.0);
    surface.Data.SetValue(1, 2, 2.0, 11.0, 21.0);
    surface.Data.SetValue(2, 2, 1.3, 20.0, 20.0);
    

    The following figure displays the generated surface as well as the order of X and Z indices in the surface grid:

    The GetValueY, GetValueX and GetValueZ methods help you read the value at the specified X and Z indices. They returns either a System.Single(float) value which in the case of an invalid data point has the value of float.NaN. If either the X, Y or Z value is float.NaN, then the data point is considered invalid and the triangles that share this vertex are not renderred. The GridSizeX and GridSizeZ properties can be used to retrieve respectively the current X and Z size of the surface data.

     Mesh Surface With Custom Colors

    When the mesh surface FillMode is set to ENSurfaceFillMode.CustomColors or FrameColorMode is set to ENSurfaceFrameColorMode.CustomColors the surface will display the filling/frame with custom colors per vertex. In this case, you also need to pass a color value for each vertex. This is achieved by using the SetColor method of the mesh surface data object - for example:

    C#
    Copy Code
    surface.Data.UseColors = true;
    surface.Data.SetColor(0, 0, Color.Red);
    
     Passing Large Amounts of Data

    When you have to feed large amounts of data to the mesh surface series using the SetValue(X/Y/Z) and SetColor methods will not be very efficient because it results in a function call for each value or color that is set. In such cases, you can consider adding data using unsafe code in which case you directly modify the surface data object in memory. The following code shows how to achieve this:

    C#
    Copy Code
    // create a surface series
    NGridSurfaceSeries gridSurface = new NGridSurfaceSeries();
    // add the series to the chart series collection
    chart.Series.Add(gridSurface);
    gridSurface.Data.HasColor = true;
    gridSurface.Data.SetGridSize(10, 10);
    unsafe
    {
        fixed (byte* pData = &meshSurface.Data.Data[0])
        {
            int dataItemSize = meshSurface.Data.DataItemSize;
            float* gridValues = (float*)pData;
            uint* gridColors = (uint*)(pData + meshSurface.Data.ColorOffset);
            int row = 1;
            int col = 1;
            int dataPointIndex = meshSurface.Data.RowCount * row + col;
            gridValues[dataPointIndex * dataItemSize] = 20; // same as calling SetValueX(1, 1, 20);
            gridValues[dataPointIndex * dataItemSize + 1] = 20; // same as calling SetValueY(1, 1, 20);
            gridValues[dataPointIndex * dataItemSize + 2] = 20; // same as calling SetValueZ(1, 1, 20);
            gridColors[dataPointIndex * dataItemSize] = 0xFF0000; // same as calling SetColor(0, 0, Color.Blue);
        }
    }
    // notify the surface that data has changed
    gridSurface.Data.OnDataChanged();
    
    See Also

    Charts

    Cartesian